import axios, { AxiosRequestConfig, AxiosResponse, RS } from 'axios'
import fileDownload from 'js-file-download'
import qs from 'qs'

const CONTENT_TYPE = 'Content-Type'

enum ContentTypeEnum {
  FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8',
  APPLICATION_JSON = 'application/json;charset=UTF-8',
  EXT_PLAIN = 'text/plain;charset=UTF-8'
}

const instance = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
  timeout: 10 * 60 * 1000
})

const checkLoginStatus = (errNo: number) => {
  // 根据实际情况设置错误码
  if ([401, 4001, 4002, 4003, 4004, 4005].includes(errNo)) {
    window.localStorage.removeItem('isLogin')
    const location = router.options.history.location.split('?')
    const redirect = location[0]
    router.push({ path: '/login', query: { redirect, ...qs.parse(location[1] || '') }, replace: true })
  }
}

instance.interceptors.request.use(
  (config: AxiosRequestConfig<RS>) => {
    if (!config.headers) {
      config.headers = {}
    }
    const store = useUserStore()
    config.headers.Authorization = store.token
    if (!config.headers[CONTENT_TYPE]) {
      config.headers[CONTENT_TYPE] = ContentTypeEnum.APPLICATION_JSON
    }
    if (config.headers[CONTENT_TYPE] === ContentTypeEnum.FORM_URLENCODED) {
      config.params = qs.stringify(config.data)
    }
    return config
  },
  error => {
    return Promise.reject(error.response)
  }
)
instance.interceptors.response.use(
  (response: AxiosResponse<RS>): AxiosResponse<RS> => {
    const { status, data, headers } = response
    const { msg, err_no: errNo } = data

    if (status === 200) {
      // if (!ContentTypeEnum.APPLICATION_JSON.includes(headers['content-type'])) {
      //   const fileName = decodeURIComponent(headers['content-disposition'].split('filename=')[1])
      //   fileDownload(data as unknown as ArrayBuffer, fileName)
      // }
      if (data instanceof Blob) {
        // Blob数据处理 以及blob数据类型中返回的错误信息捕获
        const reader = new FileReader()
        reader.onload = () => {
          try {
            const result = JSON.parse(reader.result as string)
            if (result.err_no) {
              // 存在错误信息
              Message.error(result.msg)
              checkLoginStatus(result.err_no)
            }
          } catch {
            const fileName = decodeURIComponent((headers['content-disposition'] as string).split('filename=')[1])
            fileDownload(data as unknown as ArrayBuffer, fileName)
          }
        }
        reader.readAsText(data as unknown as Blob)
      }
       checkLoginStatus(errNo)
      return response
    }
    console.error('请求失败，未知异常', response)
    throw new Error('请求失败，未知异常')
  },
  error => {
    return Promise.reject(new Error(error.message || '服务器异常，请稍后重试…'))
  }
)

class CAxios {
  static async get<T = any>(url: string, data?: Record<string, string>, config?: AxiosRequestConfig) {
    const params = Object.assign(data || {}, {})
    return instance.get<T, any>(url, { ...config, params })
  }

  static async post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<RS<T>> {
    const response = await instance.post<RS<T>>(url, data, config)

    if (response.data.code === 1) {
      return response.data
    }
    throw new Error(response.data.msg)
  }

  static async put<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<RS<T>> {
    const response = await instance.put<RS<T>>(url, data, config)
    if (response.data.code === 1) {
      return response.data
    }
    throw new Error(response.data.msg)
  }

  static async delete<T>(url: string, config?: AxiosRequestConfig): Promise<RS<T>> {
    const response = await instance.delete<RS<T>>(url, config)
    if (response.data.code === 1) {
      return response.data
    }
    throw new Error(response.data.msg)
  }

  static async downloadG<T = any>(url: string, config?: AxiosRequestConfig): Promise<RS<T>> {
    const response = await instance.get<RS<T>>(url, config)
    return response.data
  }

  static async downloadP<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<RS<T>> {
    const response = await instance.post<RS<T>>(url, data, config)
    return response.data
  }
}

export const { get, post, put, delete: remove, downloadP } = CAxios
export const CustomHttp: Record<string, any> = {
  get: CAxios.get,
  post: CAxios.post,
  delete: CAxios.delete,
  put: CAxios.put,
  downloadG: CAxios.downloadG,
  downloadP: CAxios.downloadP
}
export default instance
